﻿using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Reflection;

namespace Tszy.Unlimited.Data.AdoNet.Sql
{
    /// <summary>
    /// 数据模型接口。
    /// </summary>
    public interface IDataModel
    {
        /// <summary>
        /// 获得主键名。
        /// </summary>
        /// <returns>主键名。</returns>
        string GetTableKey();

        /// <summary>
        /// 获得表名。
        /// </summary>
        /// <returns>表名。</returns>
        string GetTableName();
    }

    /// <summary>
    /// 数据模型基类。
    /// </summary>
    public abstract class DataModelBase : IDataModel
    {
        /// <summary>
        /// 初始化。
        /// </summary>
        protected DataModelBase()
        {
        }

        /// <summary>
        /// 获得主键名。
        /// </summary>
        /// <returns>主键名。</returns>
        public virtual string GetTableKey()
        {
            return "Id";
        }

        /// <summary>
        /// 获得表名。
        /// </summary>
        /// <returns>表名。</returns>
        public abstract string GetTableName();

        #region 辅助方法

        /// <summary>
        /// 获得主键的值。
        /// </summary>
        /// <returns>主键值。</returns>
        public abstract object GetIdentity();

        /// <summary>
        /// 改变当前实体编号。
        /// </summary>
        /// <param name="identity">实体编号。</param>
        /// <returns>修改成功则返回 True，否则返回 False。</returns>
        public abstract bool ChangeCurrentIdentity(object identity);

        /// <summary>
        /// 验证主键的值是否有效。
        /// </summary>
        /// <returns>有效则返回 True，否则返回 False。</returns>
        public bool ValidateCurrentIdentity()
        {
            return ValidateIdentity();
        }

        /// <summary>
        /// 验证主键的值是否有效。
        /// </summary>
        /// <returns>有效则返回 True，否则返回 False。</returns>
        protected abstract bool ValidateIdentity();

        #endregion 辅助方法
    }

    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="TIdentity"></typeparam>
    public abstract class DataModelBase<TIdentity> : DataModelBase
    {
        /// <summary>
        /// 唯一标识。
        /// </summary>
        [Key]
        public TIdentity Id { get; set; }

        /// <summary>
        /// 改变当前实体编号。
        /// </summary>
        /// <param name="identity">实体编号。</param>
        /// <returns>修改成功则返回 True，否则返回 False。</returns>
        public override bool ChangeCurrentIdentity(object identity)
        {
            Id = (TIdentity)Convert.ChangeType(identity, typeof(TIdentity));
            return true;
        }

        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public override string GetTableName()
        {
            return GetType().GetCustomAttribute<TableAttribute>(false)?.Name;
        }
    }

    /// <summary>
    ///
    /// </summary>
    public abstract class DataModelIntBase : DataModelBase<int>
    {
        /// <summary>
        /// 获得主键的值。
        /// </summary>
        /// <returns>主键值。</returns>
        public override object GetIdentity()
        {
            return Id;
        }

        /// <summary>
        /// 验证主键的值是否有效。
        /// </summary>
        /// <returns>有效则返回 True，否则返回 False。</returns>
        protected override bool ValidateIdentity()
        {
            return Id > 0;
        }
    }

    /// <summary>
    ///
    /// </summary>
    public abstract class DataModelLongBase : DataModelBase<long>
    {
        /// <summary>
        /// 获得主键的值。
        /// </summary>
        /// <returns>主键值。</returns>
        public override object GetIdentity()
        {
            return Id;
        }

        /// <summary>
        /// 验证主键的值是否有效。
        /// </summary>
        /// <returns>有效则返回 True，否则返回 False。</returns>
        protected override bool ValidateIdentity()
        {
            return Id > 0;
        }
    }

    /// <summary>
    ///
    /// </summary>
    public abstract class DataModelGuidBase : DataModelBase<Guid>
    {
        /// <summary>
        /// 获得主键的值。
        /// </summary>
        /// <returns>主键值。</returns>
        public override object GetIdentity()
        {
            return Id;
        }

        /// <summary>
        /// 验证主键的值是否有效。
        /// </summary>
        /// <returns>有效则返回 True，否则返回 False。</returns>
        protected override bool ValidateIdentity()
        {
            return Id != Guid.Empty;
        }
    }

    /// <summary>
    ///
    /// </summary>
    public abstract class DataModelStringBase : DataModelBase<string>
    {
        /// <summary>
        /// 获得主键的值。
        /// </summary>
        /// <returns>主键值。</returns>
        public override object GetIdentity()
        {
            return Id;
        }

        /// <summary>
        /// 验证主键的值是否有效。
        /// </summary>
        /// <returns>有效则返回 True，否则返回 False。</returns>
        protected override bool ValidateIdentity()
        {
            return !string.IsNullOrWhiteSpace(Id);
        }
    }

    /// <summary>
    ///
    /// </summary>
    public abstract class DbModelIdentityInt : DataModelIntBase { }

    /// <summary>
    ///
    /// </summary>
    public abstract class DbModelIdentityLong : DataModelLongBase { }

    /// <summary>
    ///
    /// </summary>
    public abstract class DbModelIdentityGuid : DataModelGuidBase { }

    /// <summary>
    ///
    /// </summary>
    public abstract class DbModelIdentityString : DataModelStringBase { }
}